package com.societyGames.flashForms 
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import com.societyGames.system.EventObject;
	import flash.events.MouseEvent;
	/**
	 * ...
	 * @author ...
	 */
	public class ExpanderHeaderContainer extends SingleChildContainer
	{
		private var _currentIndicator:DisplayObject;				//The indicator in the header.
		private var _currentIndicatorOriginalWidth:Number;	//The original size of the indicator.
		private var _currentIndicatorOriginalHeight:Number;
		private var _collapsedIndicator:DisplayObject;				//Graphics for indicators
		private var _expandedIndicator:DisplayObject;
		private var _collapsedOverIndicator:DisplayObject;
		private var _expandedOverIndicator:DisplayObject;
		
		private var _desiredWidth:Number;					//How wide we should be set to.
		private var _desiredHeight:Number;
		private var _sizeChangedEventObject:EventObject;
		private var _isExpandedChangedEventObject:EventObject;
		private var _isExpanded:Boolean;			//Whether the expander is expanded.
		private var _isMouseOver:Boolean;
		private var _childOriginalHeight:Number;
		
		public function ExpanderHeaderContainer(collapsed:DisplayObject, expanded:DisplayObject, collapsedOver:DisplayObject = null, expandedOver:DisplayObject = null) 
		{
			this._sizeChangedEventObject = new EventObject(this, "SIZE_CHANGED");
			this._isExpandedChangedEventObject = new EventObject(this, "CLICK");
			
			this.addEventListener(MouseEvent.CLICK, clickHandler);
			this.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
			this.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
			
			this._collapsedIndicator = collapsed;
			this._collapsedIndicator.visible = false;
			this.addChild(this._collapsedIndicator);
			
			this._expandedIndicator = expanded;
			this._expandedIndicator.visible = false;
			this.addChild(this._expandedIndicator);
			
			this._collapsedOverIndicator = collapsedOver;
			if (this._collapsedOverIndicator != null)
			{
				this._collapsedOverIndicator.visible = false;
				this.addChild(this._collapsedOverIndicator);
			}
			
			this._expandedOverIndicator = expandedOver;
			if (this._expandedOverIndicator != null)
			{
				this._expandedOverIndicator.visible = false;
				this.addChild(this._expandedOverIndicator);
			}

			this.useHandCursor = true;
			this.buttonMode = true;
			
			this._isExpanded = false;
			this._isMouseOver = false;
			//Set everything up.
			recalculate();
		}
		
		public function get isExpanded():Boolean
		{
			return this._isExpanded;
		}
		
		public function set isExpanded(value:Boolean):void
		{
			if (value != this._isExpanded)
			{
				this._isExpanded = value;
				recalculate();
				this._isExpandedChangedEventObject.dispatchEvent();
			}
		}

		public function get sizeChangedEventObject():EventObject
		{
			return this._sizeChangedEventObject;	
		}
		
		public function get isExpandedChangedEventObject():EventObject
		{
			return this._isExpandedChangedEventObject;
		}
		
		public override function set height(value:Number):void
		{
			if (value != this._desiredHeight)
			{
				this._desiredHeight = value;
				recalculateHeight();
			}
		}
		
		public override function set width(value:Number):void
		{
			if (value != this._desiredWidth)
			{
				this._desiredWidth = value;
				recalculate();
			}
		}

		public override function set child(value:DisplayObject):void
		{
			//Store the original height before any recalculation happens.
			if (value != null)
			{
				this._childOriginalHeight = value.height;
			}
			//Store it normally.
			super.child = value;
		}
		
		override protected function childSizeChangedHandler(event:Event):void 
		{
			super.childSizeChangedHandler(event);
			recalculate();
		}
		
		public function get desiredHeight():Number
		{
			return Math.max(this._currentIndicatorOriginalHeight, this._childOriginalHeight);
		}
		
		private function clickHandler(event:MouseEvent):void
		{
			this.isExpanded = !this._isExpanded;
		}
	
		
		private function rollOverHandler(event:MouseEvent):void
		{
			this._isMouseOver = true;
			recalculate();
		}
		
		private function rollOutHandler(event:MouseEvent):void
		{
			this._isMouseOver = false;
			recalculate();
		}
		
		private function recalculate():void
		{	
			var oldWidth:Number = this.width;
			var oldHeight:Number = this.height;

			//Choose an indicator
			var newIndicator:DisplayObject;
			if (this._isExpanded)
			{
				if (this._isMouseOver && this._expandedOverIndicator != null)
				{
					newIndicator = this._expandedOverIndicator;
				}
				else
				{
					newIndicator = this._expandedIndicator;
				}
			}
			else //Not expanded
			{
				if (this._isMouseOver && this._collapsedOverIndicator != null)
				{
					newIndicator = this._collapsedOverIndicator;
				}
				else
				{
					newIndicator = this._collapsedIndicator;
				}
			}
			if (newIndicator != this._currentIndicator)
			{
				if (this._currentIndicator != null)
				{
					//Remove old indicator.
					this._currentIndicator.width = this._currentIndicatorOriginalWidth;
					this._currentIndicator.height = this._currentIndicatorOriginalHeight;
					this._currentIndicator.visible = false;
				}
				//Set new indicator.
				this._currentIndicator = newIndicator;
				this._currentIndicatorOriginalWidth = this._currentIndicator.width;
				this._currentIndicatorOriginalHeight = this._currentIndicator.height;
				this._currentIndicator.visible = true;
			}

			//Calculate the width
			if (this._currentIndicatorOriginalWidth < this._desiredWidth) ////Both header and indicator should fit horizontally.
			{
				this._currentIndicator.width = this._currentIndicatorOriginalWidth;
				//Let the header take the rest.
				if (this._child != null)
				{
					this._child.x = this._currentIndicator.x + this._currentIndicator.width;
					this._child.width = this._desiredWidth - this._currentIndicator.width;
				}
			}
			else
			{
				this._currentIndicator.width = this._desiredWidth;
				if (this._child != null)
				{
					this._child.x = this._currentIndicator.x + this._currentIndicator.width;
					this._child.width = 0;
				}
			}
			
			recalculateHeight();

			if (oldWidth != this.width || oldHeight != this.height)
			{
				this._sizeChangedEventObject.dispatchEvent();
			}
		}
		
		private function recalculateHeight():void
		{
			centerOrScaleVertically(this._currentIndicator, this._currentIndicatorOriginalHeight);
			if (this._child != null)
			{	
				trace("Original height: " + this._childOriginalHeight);
				trace("Desired height: " + this._desiredHeight);
				centerOrScaleVertically(this._child, this._childOriginalHeight);
				trace("Choice: " + this._child.height);
			}
		}
		
		private function centerOrScaleVertically(displayObject:DisplayObject, displayObjectDefaultHeight:Number):void
		{
			if (this._desiredHeight < displayObjectDefaultHeight)
			{
				displayObject.y = 0;
				displayObject.height = this._desiredHeight;
			}
			else
			{
				displayObject.height = displayObjectDefaultHeight;
				displayObject.y = (this._desiredHeight - displayObject.height) / 2;				
			}
		}
	}
}